package com.hnu.store.service.impl;

import com.hnu.store.dto.TradeDTO;
import com.hnu.store.entity.Sale;
import com.hnu.store.entity.Trade;
import com.hnu.store.entity.User;
import com.hnu.store.entity.Work;
import com.hnu.store.mapper.SaleMapper;
import com.hnu.store.mapper.TradeMapper;
import com.hnu.store.mapper.UserMapper;
import com.hnu.store.mapper.WorkMapper;
import com.hnu.store.service.ITradeService;
import com.hnu.store.service.ex.ChangeSaleException;
import com.hnu.store.service.ex.EditNftException;
import com.hnu.store.service.ex.ServiceException;
import com.hnu.store.service.ex.TradeInsertException;
import com.hnu.store.service.ex.TradeNotExistException;
import com.hnu.store.utils.PdfUtils;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import org.springframework.amqp.rabbit.core.RabbitTemplate;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.stereotype.Service;

@Service
public class TradeServiceImpl implements ITradeService {

  @Autowired
  private TradeMapper tradeMapper;
  @Autowired
  private WorkMapper workMapper;
  @Autowired
  private UserMapper userMapper;
  @Autowired
  private SaleMapper saleMapper;

  @Autowired
  private StringRedisTemplate redisTemplate;

  @Autowired
  private RabbitTemplate rabbitTemplate;


  @Override
  public List<TradeDTO> getTradeListById(Integer userId) {
    List<Trade> tradeList = tradeMapper.getTradeList(userId);
    if (tradeList.isEmpty()) {
      throw new TradeNotExistException("该用户不存在交易信息");
    }

    ArrayList<TradeDTO> recordList = new ArrayList<>();
    for (Trade item : tradeList) {
      TradeDTO record = new TradeDTO();
      record.setId(item.getId());
      record.setTradeTime(item.getTradeTime());
      record.setPrice(item.getTradePrice());
      record.setTradeType((item.getStatus() == 1) ? "使用权" : "所有权");
      System.out.println(item.getWorkId());
      Work goods = workMapper.getWorkById(item.getWorkId());
      record.setFileHash(goods.getFileHash());
      record.setGoodsName(goods.getWorkName());
      record.setTradeCertification(item.getTradeCertification());
      switch (goods.getType()) {
        case 1:
          record.setGoodsType("摄影作品");
          break;
        case 2:
          record.setGoodsType("文字作品");
          break;
        case 3:
          record.setGoodsType("影视作品");
          break;
        case 4:
          record.setGoodsType("音乐作品");
          break;
        case 5:
          record.setGoodsType("美术作品");
          break;
        default:
          record.setGoodsType("未设定");
          break;
      }

      record.setSellName(userMapper.findById(item.getSellId()).getUsername());
      record.setBuyName(userMapper.findById(item.getBuyId()).getUsername());
      record.setTxHash(item.getTxHash());
      recordList.add(record);
    }
    return recordList;
  }

  @Override
  public Trade getTradeById(Integer tradeId) {
    Trade trade = tradeMapper.getTradeById(tradeId);
    if (trade == null) {
      throw new TradeNotExistException("该无此交易信息");
    }
    return trade;
  }

  @Override
  public List<TradeDTO> getTradeListByIdOrder(Integer userId, String sortType) {
    List<Trade> tradeList = new ArrayList<>();
    if (sortType.equals("升序")) {
      tradeList = tradeMapper.getTradeListAscByTime(userId);
    } else if (sortType.equals("降序")) {
      tradeList = tradeMapper.getTradeListDescByTime(userId);
    }

    if (tradeList.isEmpty()) {
      throw new TradeNotExistException("该用户不存在交易信息");
    }

    ArrayList<TradeDTO> recordList = new ArrayList<>();
    for (Trade item : tradeList) {
      TradeDTO record = new TradeDTO();
      record.setId(item.getId());
      record.setTradeTime(item.getTradeTime());
      record.setPrice(item.getTradePrice());
      record.setTradeType((item.getStatus() == 1) ? "使用权" : "所有权");
      record.setTradeCertification(item.getTradeCertification());
      Work goods = workMapper.getWorkById(item.getWorkId());

      record.setGoodsName(goods.getWorkName());
      switch (goods.getType()) {
        case 1:
          record.setGoodsType("摄影作品");
          break;
        case 2:
          record.setGoodsType("文字作品");
          break;
        case 3:
          record.setGoodsType("影视作品");
          break;
        case 4:
          record.setGoodsType("音乐作品");
          break;
        case 5:
          record.setGoodsType("美术作品");
          break;
        default:
          record.setGoodsType("未设定");
          break;
      }

      record.setSellName(userMapper.findById(item.getSellId()).getUsername());
      record.setBuyName(userMapper.findById(item.getBuyId()).getUsername());
      record.setTxHash(item.getTxHash());
      recordList.add(record);
    }
    return recordList;
  }

  @Override
  public List<TradeDTO> getAllTrade() {
    List<Trade> tradeList = tradeMapper.getAllTrade();
    List<TradeDTO> dtoList = new ArrayList<>();
    for (Trade item : tradeList) {
      Work work = workMapper.getWorkById(item.getWorkId());
      String workType;
      switch (work.getType()) {
        case 1:
          workType = "摄影作品";
          break;
        case 2:
          workType = "文字作品";
          break;
        case 3:
          workType = "影视作品";
          break;
        case 4:
          workType = "音乐作品";
          break;
        case 5:
          workType = "美术作品";
          break;
        default:
          workType = "未设定";
          break;
      }

      dtoList.add(new TradeDTO(item.getId(), work.getWorkName() , item.getTradeTime(), workType,
          (item.getStatus() == 1) ? "使用权" : "所有权",
          userMapper.findById(item.getSellId()).getUsername(),
          userMapper.findById(item.getBuyId()).getUsername(), item.getTradePrice(),
          item.getTxHash(),""));
    }
    return dtoList;
  }

  //  购买使用权实现
  @Override
  public void buyUseRight(Trade trade) {

    /*
      获取售单信息
      trade里面传了buyId,saleId,txHash,status
     */
    Sale sale = saleMapper.getSaleById(trade.getSaleId());
    User user = userMapper.findById(trade.getBuyId());
    Work work = workMapper.getWorkById(trade.getWorkId());

    //  使用redis对商品数量work.num进行原子减
    String saleId = String.valueOf(sale.getId());
    long count = redisTemplate.opsForValue().increment("sale:" + saleId, -1);
    if(count<0) {
      throw new ServiceException("商品数目不足");
    }
    trade.setTradePrice(sale.getPrice());
    trade.setSellId(sale.getUserId());
    trade.setWorkId(sale.getWorkId());
    //  设置交易时间
    trade.setTradeTime(new Date());
    //  使用权
    trade.setIsOwn(0);
    sale.setAuthorizeNum(sale.getAuthorizeNum() + 1);
    PdfUtils pdfUtils = new PdfUtils();
    //  获取文件路径
    String certificateFileLocation = pdfUtils.useRightCertificatePdfOut(work,trade,user);
    //  设置下载路径
    trade.setTradeCertification("http://124.222.70.223:8081/work/downloadNft?filePath="
    + certificateFileLocation + "&fileName=UseRightCertificate.pdf");

    if (saleMapper.update(sale) != 1) {
      throw new ChangeSaleException("售单授权数目更新失败");
    }

    if (tradeMapper.insert(trade) != 1) {
      throw new TradeInsertException("创建交易失败");
    }

    //  添加一条消息
    rabbitTemplate.convertAndSend("","trade_queue",trade);
  }

  //  购买所有权实现
  @Override
  public void buyOwnRight(Trade trade,String chainTime,String blockHeight) {
    /*
      获取售单信息
      trade里面传了buyId,saleId,txHash,status
     */
    Sale sale = saleMapper.getSaleById(trade.getSaleId());
    Work work = workMapper.getWorkById(sale.getWorkId());
    //  购买者id传入得到购买者user
    Integer buyId = trade.getBuyId();
    User user = userMapper.findById(buyId);
    trade.setTradePrice(sale.getPrice());
    trade.setSellId(sale.getUserId());
    trade.setWorkId(sale.getWorkId());
    //  设置交易时间
    trade.setTradeTime(new Date());

    trade.setIsOwn(1);

    //  更新work表
    work.setUserId(buyId);
    work.setCopyrightOwnerName(user.getRealName());
    work.setCopyrightOwnerId(user.getCitizenId());

    if (workMapper.update(work) != 1) {
      throw new EditNftException("转让所有权更新nft信息错误");
    }

    //  更新sale表
    if (saleMapper.delete(sale.getId())!= 1) {
      throw new ChangeSaleException("删除售单失败");
    }

    if (tradeMapper.insert(trade) != 1) {
      throw new TradeInsertException("创建交易失败");
    }
  }

  @Override
  public Double getTodayEarning(Integer userId) {
    List<Trade> sellTrade = tradeMapper.getSellTrade(userId);
    Double earning = 0.0;
    Date today = new Date();
    String s1 = String.format("%tY-%tm-%td",today,today,today);
    for (Trade trade : sellTrade) {
      /*
      Date转为LocalDate
       */
      Date date = trade.getTradeTime();
      String s2 = String.format("%tY-%tm-%td", date, date, date);

      if (s1.equals(s2)) {
        earning += trade.getTradePrice();
      }
    }
    return earning;
  }

  @Override
  public void viewDetails(Integer tradeId,String chainTime,String blockHeight) {
    Trade trade = tradeMapper.getTradeById(tradeId);
    Sale sale = saleMapper.getSaleByWorkId(trade.getWorkId());
    Work work = workMapper.getWorkById(trade.getWorkId());
    User user = userMapper.findById(trade.getBuyId());

    //  所有权需要生成存证文件，使用权的存证文件已经在交易时生成了
    if(sale==null&&trade.getTradeCertification()==null) {
      PdfUtils pdfUtils = new PdfUtils();
      //  获取文件路径
      String certificateFileLocation = pdfUtils.ownerShipCertificatePdfOut(work,trade,user,chainTime,blockHeight);
      //  设置下载路径
      trade.setTradeCertification("http://124.222.70.223:8081/work/downloadNft?filePath="
          + certificateFileLocation + "&fileName=OwnershipCertificate.pdf");
      tradeMapper.update(trade);
    }
  }

}
